//CSE 430 - Operating Systems
//Partha Dasgupta
//Spring '12
//Project 3

//Alan Tu
//Kelly Jesionowski

#include <stdio.h>
#include "sem.h"

//Implement a set of threads to test the semaphores. Choose a method (second better):
//M1: Each thread is an infinite loop, and has a critical section using a mutex semaphore. The thread gets into the CS, prints values of global and local variables (like proj2),
//  //sleeps and exits the CS. Then it prints a message and //sleeps and then repeats.
//M2: Write a producer/consumer solution, using the code given in class (see notes). Run 2 producers and 2 consumers. You will have to work out some details. If you choose to do
//  this you really should do mehtod 1 first. Also, doing this will make it easier for you to do project 4...

//Part of M1...
//semaphore_t *s;
//int globVal = 0;


//Part of M2...
#define BUFF_SIZE 5
semaphore_t *full;
semaphore_t *empty;
int buffer[BUFF_SIZE];
int in, out;

//Part of M1...
/*
void f1(){
	int locVal;
	printf("** Starting function 1 **\n");
	//sleep(1);
	yield();
    while(1){
		printf("Function 1 calling P(s)...\n");
		//sleep(1);
        P(&s);
        printf("\nFunction 1 in CS...\n");
        //sleep(1);
        printf("Function 1 incrementing values by 1...\n");
        locVal = locVal+1;
        globVal = globVal+1;
        printf("\tLocal: %d\tGlobal: %d\n\n", locVal, globVal);
        //sleep(1);
		printf("Function 1 calling V(s)...\n");
        V(&s);
    }
}

void f2(){
	int locVal;
	printf("** Starting function 2 **\n");
	//sleep(1);
	yield();
    while(1){
		printf("Function 2 calling P(s)...\n");
		//sleep(1);
        P(&s);
        printf("\nFunction 2 in CS...\n");
        //sleep(1);
        printf("Function 2 incrementing values by 2...\n");
        locVal = locVal+2;
        globVal = globVal+2;
        printf("\tLocal: %d\tGlobal: %d\n\n", locVal, globVal);
        //sleep(1);
		printf("Function 2 calling V(s)...\n");
        V(&s);
    }
}

void f3(){
	int locVal;
	printf("** Starting function 3 **\n");
	//sleep(1);
	yield();
    while(1){
		printf("Function 3 calling P(s)...\n");
		//sleep(1);
        P(&s);
        printf("\nFunction 3 in CS...\n");
        //sleep(1);
        printf("Function 3 incrementing values by 3...\n");
        locVal = locVal+3;
        globVal = globVal+3;
        printf("\tLocal: %d\tGlobal: %d\n\n", locVal, globVal);
        //sleep(1);
		printf("Function 3 calling V(s)...\n");
        V(&s);
    }
}

void f4(){
	int locVal;
	printf("** Starting function 4 **\n");
	//sleep(1);
	yield();
    while(1){
		printf("Function 4 calling P(s)...\n");
		//sleep(1);
        P(&s);
        printf("\nFunction 4 in CS...\n");
        //sleep(1);
        printf("Function 4 incrementing values by 4...\n");
        locVal = locVal+4;
        globVal = globVal+4;
        printf("\tLocal: %d\tGlobal: %d\n\n", locVal, globVal);
        //sleep(1);
		printf("Function 4 calling V(s)...\n");
        V(&s);
    }
}
*/

void printBuff(){
	int i, n;
	printf("Buffer: ");
	for(i = 0; i < BUFF_SIZE; i++){
		if(buffer[i] != 0){
			printf("%d ", buffer[i]);
		}
	}
	printf("\n");
}

void producer(){
	int item;
	while(1){
		item = rand() % 100;
		P(&full);
		printf("Producing item: %d\n", item);
		buffer[in] = item;
		printBuff();
		in = (in+1) % BUFF_SIZE;
		V(&empty);
		/*if((item % 7) == 0){
			start_thread(producer);
		}*/
	}
}

void consumer(){
	int item;
	while(1){
		P(&empty);
		item = buffer[out];
		printf("Consuming item: %d\n\n", item);
		buffer[out] = 0;
		out = (out+1) % BUFF_SIZE;
		V(&full);
		/*if((item % 3) == 0){
			start_thread(consumer);
		}*/
	}
}

void main(){
    //initSem(&s, 1);
	initSem(&full, BUFF_SIZE);
	initSem(&empty, 0);
    InitQueue(&readyQ);
    
	start_thread(producer);
	start_thread(producer);
	start_thread(consumer);
	start_thread(consumer);
/*
    start_thread(f1);
    start_thread(f2);
    start_thread(f3);
    start_thread(f4);
*/
    
    run();
}
